#include <linux/module.h>
#include <linux/init.h>

#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>

#include <asm/ptrace.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("chzhou");

struct tasklet_struct my_tasklet;

void tasklet_action(unsigned long arg)
{
    //dump_stack();
    printk("[%s %d ] arg=0x%x\n", __FUNCTION__, __LINE__, arg);
    //ssleep(3); /* tasklet is not running at process context, cannot sleep */
}

static irqreturn_t irq_handle(int irq, void *dev_id)
{
    tasklet_schedule(&my_tasklet);
    printk("[%s %d ] data = %d\n", __FUNCTION__, __LINE__, (int)dev_id);

    return IRQ_HANDLED;
}

int dev_init(void)
{
    int ret = 0;

    tasklet_init(&my_tasklet, tasklet_action, 789);
    set_irq_type(IRQ_EINT8, IRQ_TYPE_EDGE_RISING);

    ret = request_irq(IRQ_EINT8, irq_handle, 0, "mini2440-button", (void *)123);
    if (ret) {    
        printk("request irq failed.\n");
        return -EBUSY;
    }

    printk("[%s %d ]\n", __FUNCTION__, __LINE__);

    return 0;
}

void dev_exit(void)
{
    free_irq(IRQ_EINT8, (void *)123);
    printk("[%s %d ]\n", __FUNCTION__, __LINE__);
}

module_init(dev_init);
module_exit(dev_exit);

// http://blogold.chinaunix.net/u4/120285/showart_2535026.html
